package com.lab.service;

import com.lab.common.*;
import com.lab.dto.LoginDTO;
import com.lab.entity.User;
import com.lab.mapper.LoginMapper;
import com.lab.vo.LoginVO;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.util.Assert;
import org.springframework.util.DigestUtils;

import java.nio.charset.StandardCharsets;
import java.util.HashMap;
import java.util.Map;
import java.util.Objects;

@Service
@Slf4j
public class LoginService {

    @Autowired
    private LoginMapper loginMapper;

    @Autowired
    private JwtProperties jwtProperties;

    /**
     * 统一登录处理（保留MD5加密方式）
     */
    public LoginVO login(LoginDTO dto) {
        // 参数校验
        validateLoginParams(dto);

        // 查询用户信息
        User user = loginMapper.getUserByAccount(dto.getAccount());
        if (Objects.isNull(user)) {
            log.warn("登录失败：账号不存在，account={}", dto.getAccount());
            throw new BusinessException(401, "账号不存在或已禁用（支持学生学号/姓名、老师/管理员姓名登录）");
        }

        // 角色校验
        String role = user.getRole();
        if (!RoleConstant.ALLOWED_ROLES.contains(role)) {
            log.warn("登录失败：不支持的角色，role={}, account={}", role, dto.getAccount());
            throw new BusinessException(403, "当前角色不允许登录");
        }

        // 密码校验（保留MD5加密）
        String encryptedPwd = DigestUtils.md5DigestAsHex(dto.getPassword().getBytes(StandardCharsets.UTF_8));
        if (!encryptedPwd.equals(user.getPassword())) {
            log.warn("登录失败：密码错误，account={}", dto.getAccount());
            throw new BusinessException(401, "密码错误");
        }

        // 生成令牌
        String token = generateToken(user, role);

        // 封装返回结果
        return buildLoginVO(user, role, token);
    }

    /**
     * 参数校验
     */
    private void validateLoginParams(LoginDTO dto) {
        Assert.hasText(dto.getAccount(), "账号不能为空");
        Assert.hasText(dto.getPassword(), "密码不能为空");
    }

    /**
     * 生成角色专属JWT令牌
     */
    private String generateToken(User user, String role) {
        Map<String, Object> claims = new HashMap<>(4);
        claims.put(JwtClaimsConstant.USER_ID, user.getId());
        claims.put(JwtClaimsConstant.NAME, user.getName());
        claims.put("role", role);

        // 根据角色获取对应的JWT配置
        String secretKey;
        long ttl;
        switch (role) {
            case RoleConstant.STUDENT:
                secretKey = jwtProperties.getStudent().getSecretKey();
                ttl = jwtProperties.getStudent().getTtl();
                claims.put("studentId", user.getStudentId());
                break;
            case RoleConstant.TEACHER:
                secretKey = jwtProperties.getTeacher().getSecretKey();
                ttl = jwtProperties.getTeacher().getTtl();
                break;
            case RoleConstant.ADMIN:
                secretKey = jwtProperties.getAdmin().getSecretKey();
                ttl = jwtProperties.getAdmin().getTtl();
                break;
            default:
                throw new BusinessException(500, "生成令牌失败：不支持的角色");
        }

        return JwtUtil.createJWT(secretKey, ttl, claims);
    }

    /**
     * 构建登录返回结果VO
     */
    private LoginVO buildLoginVO(User user, String role, String token) {
        LoginVO vo = new LoginVO();
        vo.setId(user.getId());
        vo.setName(user.getName());
        vo.setRole(role);
        vo.setToken(Constants.TOKEN_PREFIX + token); // 拼接令牌前缀

        // 学生额外返回学号
        if (RoleConstant.STUDENT.equals(role)) {
            vo.setStudentId(user.getStudentId());
        }

        log.info("登录成功：userId={}, role={}, name={}", user.getId(), role, user.getName());
        return vo;
    }
}